	/************************************************************************************************

		@API
		Factory:	jsl.Function

		Methods:
			f				Function			(f)
			f				augment				(f..)

			ps			parameters		()
			s				signature			()
			body		body					()

			b				isSubTypeOf		(f)
			b				isSuperTypeOf	(f)
			b				isNative			()

	************************************************************************************************/

	//-------------------------------------------------------------------------------
	jsl.Function = function(f) {
		try {
	   	var proto, rv
    	//!
      if(arguments.length > 1) throw jsl.ParamError()//!

			if(arguments.length) {//!
				jsl.validate(f, "f")//!
				if(f.__augmented)	return f
				else							rv = f
			}
			else
				rv = new Function

			proto = jsl.Function.prototype
    	for(var id in proto) rv[id] = proto[id]
    	return rv
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
  //-------------------------------------------------------------------------------
	jsl.Function.__name 			= "jsl.Function"
  jsl.Function.__native			= { __name: true, __augmented: true }
	jsl.Function.__augmented	= true
  //-------------------------------------------------------------------------------
	jsl.Function.prototype					= jsl.Object()
	jsl.Function.prototype.__name 	= "jsl.Function"
	jsl.Function.prototype.__fsgn 	= null
	jsl.Function.prototype.__params = null
	jsl.Function.prototype.__body 	= null
	jsl.Function.prototype.__native	= jsl.Object.clone(jsl.Object.prototype.__native)
	//-------------------------------------------------------------------------------
	jsl.Function.prototype.augment = function() {
		try {
			var fs, len, proto, id
			//!
     	if(!jsl.isFunction(this))	throw jsl.TypeError("BadMethodCall:Function")
			if(!arguments.length)			throw jsl.ParamError()//!

			fs 	= arguments
			len	= fs.length

			for(var a = 0; a < len; a++) {
				//!
				jsl.validate(fs[a], "f", "f[" + a + "]")//!
				proto = fs[a].prototype

				for(id in proto)
					if(typeof proto[id] === "function")
						this.prototype[id] = proto[id]
			}

			return this
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
	//-------------------------------------------------------------------------------
	jsl.Function.prototype.parameters = function() {
		try {
			var ps, txt//!
			if(arguments.length)	throw jsl.ParamError()//!

			ps = this.__params

			//very slow -> caching only on augmented object (no in static call -> it modify a base object)
			if(!ps) {
				txt	= Function.prototype.toString.call(this)
				txt = txt.replace(/\/\*(?:[\s\S])*?\*\//g, "")
				txt = txt.replace(/\/\/.*\n/g, "")
				txt = txt.replace(/[\n\s]+/g, "")
				//@sys: Explorer v.8 - args.callee + "" - > wrap the function into round brackets (function() {..})
				txt = txt.match(/[\s\S]*?function[^(]*\(([^\)]*)\)/)[1]
				ps	= txt.length ? txt.split(",") : null

				if(this.__augmented)	this.__params = ps
			}

			return ps
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
	//-------------------------------------------------------------------------------
	jsl.Function.prototype.signature = function() {
		try {
			var sgn, txt//!
     	if(!jsl.isFunction(this))	throw jsl.TypeError("BadMethodCall:Function")
			if(arguments.length)			throw jsl.ParamError()//!

			sgn = this.__fsgn

			if(!sgn) {
				txt		= Function.prototype.toString.call(this)
				txt 	= txt.replace(/\/\*(?:[\s\S])*?\*\//g, "")
				txt 	= txt.replace(/\/\/.*\n/g, "")
				txt 	= txt.replace(/[\n\s]+/g, "")

				sgn	= txt.match(/[\s\S]*?function([^(]*)/)[1] || "anonymous"
				sgn = sgn + txt.match(/(\([^)]*\))/)[1]
				if(this.__augmented)	this.__fsgn = sgn
			}

			return sgn
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
	//-------------------------------------------------------------------------------
	jsl.Function.prototype.body = function() {
		try {
			var txt, re, ix, ix2, body
			//!
     	if(!jsl.isFunction(this))	throw jsl.TypeError("BadMethodCall:Function")
			if(arguments.length)			throw jsl.ParamError()//!

			//@sys: Chrome 9/Opera 10.63 - when a function is converted into string, his content can be altered. Some \n
			//			can be deleted and can occour -> function() { ;;//txt } with a inline comment without \n terminator
			//@sys: Konqueror windows 4.4.0 kde(4.4.0) - function(){} + "" = function anonymous();
			//			A lot of borowsers oddities when a function is converted into text. If we don't find
			//			the indexes we consider the body empty

			body = this.__body

			if(body == null) {
				re		= /("(?:\\.|[^"\\])*")|('(?:\\.|[^'\\])*')|(\/\*(?:[\s\S])*?\*\/)|(\/\/[^\n]*)|(\/(?:\\.|[^\/\\])*\/)/g
				txt		= Function.prototype.toString.call(this)
				txt		= txt.replace(re, function(s, g1, g2, g3, g4, g5) { return g3 || g4 ? "" : s })
				ix		= txt.indexOf("{")
				ix2		= txt.lastIndexOf("}")
				body	= ix !== -1 && ix2 !== -1 ? txt.slice(ix + 1, ix2) : ""

				if(this.__augmented) this.__body = body
			}

			return body
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
	//-------------------------------------------------------------------------------
	jsl.Function.prototype.isSubTypeOf = function(f) {
		try {//!
      if(!jsl.isFunction(this))		throw jsl.TypeError("BadMethodCall:Function")
			if(arguments.length !== 1)	throw jsl.ParamError()
			jsl.validate(f, "f", "f")//!

			return f.prototype.isPrototypeOf(this.prototype)
		}
		catch(e) {
  		jsl.throwError(e, this, arguments)
		}
	}
	//-------------------------------------------------------------------------------
	jsl.Function.prototype.isSuperTypeOf = function(f) {
		try {//!
      if(!jsl.isFunction(this))		throw jsl.TypeError("BadMethodCall:Function")
			if(arguments.length !== 1)	throw jsl.ParamError()
			jsl.validate(f, "f", "f")//!

			return this.prototype.isPrototypeOf(f.prototype)
		}
		catch(e) {
  		jsl.throwError(e, this, arguments)
		}
	}
	//-------------------------------------------------------------------------------
	jsl.Function.prototype.isNative = function() {
		try {
			var body, re//!
      if(!jsl.isFunction(this))	throw jsl.TypeError("BadMethodCall:Function")
			if(arguments.length)			throw jsl.ParamError()//!

			body 	= jsl.Function.body(this)
			re 		= /"(\\.|[^\\"])*"|'(\\.|[^\\'])*'|\/(\\.|[^\\\/])*\//g

			return body.replace(re, "").search(/\[native code[^\]]*\]/i) !== -1
		}
		catch(e) {
  		jsl.throwError(e, this, arguments)
		}
	}

	//Function init
	//-------------------------------------------------------------------------------
	;(function() {
		var prt, Fun

		Fun = jsl.Function
		prt = Fun.prototype

		for(var id in prt) {

			Fun.__native[id] = true
			prt.__native[id] = true

			if(typeof prt[id] === "function" && !prt[id].__name) {

				Fun[id] = function(obj) {
					try {//!
						if(!arguments.length)	throw jsl.ParamError()
						if(obj == null)				throw jsl.ParamError("NullValue:obj")//!

						return arguments.callee.__f.apply(obj, Array.prototype.slice.call(arguments, 1))
					}
					catch(e) {
						jsl.throwError(e, this, arguments)
					}
				}

				Fun[id].__name	= prt[id].__name = id
				Fun[id].__f			= prt[id]
			}
		}
	})()
